#pragma once
#include "base/function.hpp"
#include "base/mutex.h"
#include "base/noncopyable.h"
#include "base/timeeverymap.h"
#include "base/timeeventset.h"
#include "base/config.h"

#include <vector>
#include <string>
#include <atomic>

#include <pthread.h>
#include <sys/eventfd.h>
namespace net_tools{

namespace base{
class Channel;
class Connectpool;
class Epoll;
class Timeevent;
class Timeevery;
class Timequeue;
} // namespace base

namespace net{
class Connectpool;
} // namespace net
class Eventloop : base::noncopyable{
 public:
  Eventloop(int size = _C::CHANNEL_DEFAULT_SIZE,int tid = 0);
  ~Eventloop();
  void Loop();
  //need run in right thread
  base::Channel* Get_free_channel(int fd);
  //already run in right thread
  void Free_channel(base::Channel* channel);
  //need run in right thread
  void Free_channel_right_now(base::Channel* channel);
  //already run in right thread
  void Addevent_right(base::Channel* channel);
  //already run in right thread
  void Modevent_right(base::Channel* channel);
  //already run in right thread
  void Delevent_right(base::Channel* channel);
  //need run in right thread
  void Addevent(base::Channel* channel);
  //need run in right thread
  void Modevent(base::Channel* channel);
  //need run in right thread
  void Delevent(base::Channel* channel);
  //判断了是否在正确线程
  void Run_in_right_thread(func func_);
  //不判断是否在正确线程，直接添加
  void Run_in_thread(func func_);
  //already run in right thread
  base::Timeevent* Run_after(func func_,timeval begin_time,base::Timeeventset* timeeventset = nullptr);
  //already run in right thread
  base::Timeevent* Run_at(func func_,timeval begin_time,base::Timeeventset* timeeventset = nullptr);
  //already run in right thread
  // 不要对io线程的eventloop本体多线程添加重名任务 如果添加的任务重名则会出现奇怪的bug
  base::Timeevery* Run_every(func func_,timeval begin_time,timeval time,int count,const std::string& job_name,base::Timeeverymap* timeeverymap = nullptr);
  //already run in right thread
  void Deltimejob_every(const std::string job_name);
  //need in right thread
  bool Deltimejob_once(base::Timeevent* timeevent);

  void Init_thread_id();
  bool Is_in_right_thread();
  std::string* Get_Thread_name();
  //for Tcp server
  net::Connectpool* connectpool_;
 private:
  void Wakeup_job();
  void Wakeup_by_other();
  void Wakeup();
  unsigned int       thread_tid;

  // 没有同步语义设置 仅x86平台可用
  std::atomic<bool>  wakeup_;
  base::Epoll*       epoll_;
  base::Timequeue*   timequeue_;
  int                wakeupfd_;
  bool               quit;
  eventfd_t          wakeup_event_use_;
  base::Mutex        mutex_;
  std::vector<func>  wakeup_job_;
  timeval            nulltime_;
  base::Timeeverymap timeeverymap_;
  base::Timeeventset timeeventset_;
};

} // namespace net_tools